/**
  ******************************************************************************
  * File Name          : queue.c
  * Description        : This file provides code for the configuration
  *                      of the Queue instances.
  ******************************************************************************
  * @attention
  * Created by Chen Lu in 20210612
  *
  ******************************************************************************
  */

#include "string.h"
#include "stdlib.h"
#include "queue.h"

/**
  * @brief  Initiate a queue.
  *
  * @note   (Nothing important)
  *
  * @param  pq	A queue instance pointer
  * @retval None
  */
void QueueInit(Queue* pq)
{
	//assert(pq);
	pq->first = NULL;
	pq->last = NULL;
}

/**
  * @brief  Destroy a queue.
  *
  * @note   (Nothing important)
  *
  * @param  pq	A queue instance pointer.
  * @retval None
  */
void QueueDestory(Queue* pq)
{
	//assert(pq);
	QueueNode* cur = pq->first;
	while (cur)
	{
		QueueNode* tmp = cur->_next;
		free(cur);
		cur = tmp;
	}
	pq->first = pq->last = NULL;
}

/**
  * @brief  Create a queue node.
  *
  * @note   (Nothing important)
  *
  * @param  x	The data in the queue node.
  * @retval QueueNode.
  */
QueueNode* BuyQueueNode(DataType x)
{
	QueueNode* tmp = (QueueNode*) malloc(sizeof(QueueNode));
	if (tmp == NULL)
	{
		printf("%s\r\n","Malloc wrong!");
	}
	tmp->_next = NULL;
	tmp->_data = x;
	return tmp;
}

/**
  * @brief  Push a node to the rear of the queue.
  *
  * @note   (Nothing important)
  *
  * @param  pq	A queue instance pointer.
  * @param  x	The data in the queue node.
  * @retval None.
  */
void QueuePush(Queue* pq, DataType x)
{
	//assert(pq);
	if (pq->first == NULL)
	{
		QueueNode* next = BuyQueueNode(x);
		pq->first = next;
		pq->last = next;
	}
	else
	{
		QueueNode* next = BuyQueueNode(x);
		pq->last->_next = next;
		pq->last = next;
	}
}

/**
  * @brief  Insert a node to the front of the queue.
  *
  * @note   (Nothing important)
  *
  * @param  pq	A queue instance pointer.
  * @param  x	The data in the queue node.
  * @retval None.
  */
void QueueInsertFront(Queue* pq, DataType x)
{
	//assert(pq);
	if (pq->first == NULL)
	{
		QueueNode* front = BuyQueueNode(x);
		pq->first = front;
		pq->last = front;
	}
	else
	{
		QueueNode* front = BuyQueueNode(x);
		front->_next = pq->first;
		pq->first = front;
	}
}

/**
  * @brief  Pop the node in the front of queue.
  *
  * @note   (Nothing important)
  *
  * @param  pq	A queue instance pointer.
  * @retval Data in the node popped.
  */
DataType QueuePop(Queue* pq)
{
	//assert(pq);
	QueueNode* next = pq->first->_next;
	DataType tmp = pq->first->_data;
	free(pq->first);
	pq->first = next;
	return tmp;
}

/**
  * @brief  Get the node in the front of queue.
  *
  * @note   (Nothing important)
  *
  * @param  pq	A queue instance pointer.
  * @retval Data in the node.
  */
DataType QueueFront(Queue* pq)
{
	//assert(pq);
	return pq->first->_data;
}

/**
  * @brief  Check whether the queue is empty.
  *
  * @note   (Nothing important)
  *
  * @param  pq	A queue instance pointer.
  * @retval Empty status.
  * 			@arg 0:	Empty
  * 			@arg 1: Not empty.
  */
int QueueEmpty(Queue* pq)
{
	//assert(pq);
	return pq->first == NULL ? 0 : 1;
}

/**
  * @brief  Get length of the queue.
  *
  * @note   (Nothing important)
  *
  * @param  pq	A queue instance pointer.
  * @retval Length.
  */
int QueueSize(Queue* pq)
{
	int size = 0;
	//assert(pq);
	QueueNode* cur = pq->first;
	while (cur)
	{
		size++;
		cur = cur->_next;
	}
	return size;
}

/**
  * @brief  Empty a queue.
  *
  * @note   (Nothing important)
  *
  * @param  pq	A queue instance pointer.
  * @retval None
  */
void QueueSetEmpty(Queue* pq)
{
	pq->first = NULL;
	pq->last = NULL;
}


